/**
 * 通用组件共同的使用的基础组件，原先放在 adapter/form 内部，限制了使用范围，这里提取出来，方便其他地方使用
 * 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
 */

import type { DatePickerProps } from 'element-plus';

import type { Component } from 'vue';

import type { BaseFormComponentType } from '@vben/common-ui';
import type { Recordable } from '@vben/types';

import {
  defineAsyncComponent,
  defineComponent,
  getCurrentInstance,
  h,
  ref,
} from 'vue';

import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
import { $t } from '@vben/locales';

import { ElNotification } from 'element-plus';
// 在顶部导入区域添加以下代码
const ElAutocomplete = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/autocomplete/index'),
    import('element-plus/es/components/autocomplete/style/css'),
  ]).then(([res]) => res.ElAutocomplete),
);
const ElButton = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/button/index'),
    import('element-plus/es/components/button/style/css'),
  ]).then(([res]) => res.ElButton),
);
const ElCheckbox = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/checkbox/index'),
    import('element-plus/es/components/checkbox/style/css'),
  ]).then(([res]) => res.ElCheckbox),
);
const ElCheckboxButton = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/checkbox/index'),
    import('element-plus/es/components/checkbox-button/style/css'),
  ]).then(([res]) => res.ElCheckboxButton),
);
const ElCheckboxGroup = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/checkbox/index'),
    import('element-plus/es/components/checkbox-group/style/css'),
  ]).then(([res]) => res.ElCheckboxGroup),
);
const ElDatePicker = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/date-picker/index'),
    import('element-plus/es/components/date-picker/style/css'),
  ]).then(([res]) => res.ElDatePicker),
);
const ElDivider = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/divider/index'),
    import('element-plus/es/components/divider/style/css'),
  ]).then(([res]) => res.ElDivider),
);
const ElInput = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/input/index'),
    import('element-plus/es/components/input/style/css'),
  ]).then(([res]) => res.ElInput),
);
// 新增文本域组件
const ElTextarea = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/input/index'),
    import('element-plus/es/components/input/style/css'),
  ]).then(([res]) => ({
    ...res.ElInput,
    // 覆盖默认类型为 textarea
    props: {
      ...res.ElInput.props,
      type: { type: String, default: 'textarea' },
    },
  })),
);
const ElInputNumber = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/input-number/index'),
    import('element-plus/es/components/input-number/style/css'),
  ]).then(([res]) => res.ElInputNumber),
);
const ElRadio = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/radio/index'),
    import('element-plus/es/components/radio/style/css'),
  ]).then(([res]) => res.ElRadio),
);
const ElRadioButton = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/radio/index'),
    import('element-plus/es/components/radio-button/style/css'),
  ]).then(([res]) => res.ElRadioButton),
);
const ElRadioGroup = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/radio/index'),
    import('element-plus/es/components/radio-group/style/css'),
  ]).then(([res]) => res.ElRadioGroup),
);
const ElSelectV2 = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/select-v2/index'),
    import('element-plus/es/components/select-v2/style/css'),
  ]).then(([res]) => res.ElSelectV2),
);
const ElSpace = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/space/index'),
    import('element-plus/es/components/space/style/css'),
  ]).then(([res]) => res.ElSpace),
);
const ElSwitch = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/switch/index'),
    import('element-plus/es/components/switch/style/css'),
  ]).then(([res]) => res.ElSwitch),
);
const ElTimePicker = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/time-picker/index'),
    import('element-plus/es/components/time-picker/style/css'),
  ]).then(([res]) => res.ElTimePicker),
);
const ElTreeSelect = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/tree-select/index'),
    import('element-plus/es/components/tree-select/style/css'),
  ]).then(([res]) => res.ElTreeSelect),
);
const ElUpload = defineAsyncComponent(() =>
  Promise.all([
    import('element-plus/es/components/upload/index'),
    import('element-plus/es/components/upload/style/css'),
  ]).then(([res]) => res.ElUpload),
);

// 这里需要自行根据业务组件库进行适配，需要用到的组件都需要在这里类型说明
export type ComponentType =
  | 'ApiAutoComplete' // 新增API自动完成类型
  | 'ApiSelect'
  | 'ApiTreeSelect'
  | 'AutoComplete' // 新增自动完成类型
  | 'Checkbox'
  | 'CheckboxGroup'
  | 'DatePicker'
  | 'Divider'
  | 'IconPicker'
  | 'Input'
  | 'InputNumber'
  | 'InputPassword' // 新增密码输入框类型
  | 'RadioGroup'
  | 'RangeDatePicker'
  | 'Select'
  | 'Space'
  | 'Switch'
  | 'Textarea' // 新增文本域类型
  | 'TimePicker'
  | 'TreeSelect'
  | 'Upload'
  | BaseFormComponentType;

async function initComponentAdapter() {
  const components: Partial<Record<ComponentType, Component>> = {
    // 如果你的组件体积比较大，可以使用异步加载
    // Button: () =>
    // import('xxx').then((res) => res.Button),

    // 基础自动完成
    AutoComplete: withDefaultAutocomplete(ElAutocomplete),

    // API自动完成
    ApiAutoComplete: withDefaultAutocomplete(ApiComponent, {
      component: ElAutocomplete,
      apiPropName: 'fetchApi', // API配置属性名
      resultPropName: 'options', // 结果列表属性名
      labelField: 'label', // 显示文本字段
      valueField: 'value', // 值字段
      queryParam: 'keyword', // 查询参数名
      // 请求适配器
      adaptResponse: (res: any) => res.data?.list || [],
      // 防抖配置
      debounce: 300,
    }),
    ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
      component: ElSelectV2,
      loadingSlot: 'loading',
      visibleEvent: 'onVisibleChange',
    }),
    ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
      component: ElTreeSelect,
      props: { label: 'label', children: 'children' },
      nodeKey: 'value',
      loadingSlot: 'loading',
      optionsPropName: 'data',
      visibleEvent: 'onVisibleChange',
    }),
    Checkbox: ElCheckbox,
    CheckboxGroup: (props, { attrs, slots }) => {
      let defaultSlot;
      if (Reflect.has(slots, 'default')) {
        defaultSlot = slots.default;
      } else {
        const { options, isButton } = attrs;
        if (Array.isArray(options)) {
          defaultSlot = () =>
            options.map((option) =>
              h(isButton ? ElCheckboxButton : ElCheckbox, option),
            );
        }
      }
      return h(
        ElCheckboxGroup,
        { ...props, ...attrs },
        { ...slots, default: defaultSlot },
      );
    },

    // 自定义默认按钮
    DefaultButton: (props, { attrs, slots }) => {
      return h(ElButton, { ...props, attrs, type: 'info' }, slots);
    },
    // 自定义主要按钮
    PrimaryButton: (props, { attrs, slots }) => {
      return h(ElButton, { ...props, attrs, type: 'primary' }, slots);
    },
    Divider: ElDivider,
    IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
      iconSlot: 'append',
      modelValueProp: 'model-value',
      inputComponent: ElInput,
    }),
    Input: withDefaultPlaceholder(withDefaultClearable(ElInput), 'input'),
    Textarea: withDefaultPlaceholder(ElTextarea, 'input'),

    InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
    // 密码输入框组件
    InputPassword: withDefaultPlaceholder(
      defineComponent({
        name: 'ElInputPassword',
        setup(props, { attrs, slots }) {
          return () =>
            h(
              ElInput,
              {
                ...props,
                ...attrs,
                type: 'password',
                showPassword: true,
                clearable: true,
              },
              slots,
            );
        },
      }),
      'input',
    ),

    RadioGroup: (props, { attrs, slots }) => {
      let defaultSlot;

      if (Reflect.has(slots, 'default')) {
        defaultSlot = slots.default;
      } else {
        const { options } = attrs;
        if (Array.isArray(options)) {
          defaultSlot = () =>
            options.map((option) =>
              h(
                props?.optionType === 'button' ? ElRadioButton : ElRadio,
                option,
              ),
            );
        }
      }
      return h(
        ElRadioGroup,
        { ...props, ...attrs },
        { ...slots, default: defaultSlot },
      );
    },
    Select: (props, { attrs, slots }) => {
      return h(withDefaultClearable(ElSelectV2), { ...props, attrs }, slots);
    },
    Space: ElSpace,
    Switch: ElSwitch,
    TimePicker: (props, { attrs, slots }) => {
      const { name, id, isRange } = props;
      const extraProps: Recordable<any> = {};
      if (isRange) {
        if (name && !Array.isArray(name)) {
          extraProps.name = [name, `${name}_end`];
        }
        if (id && !Array.isArray(id)) {
          extraProps.id = [id, `${id}_end`];
        }
      }
      return h(
        withDefaultClearable(ElTimePicker),
        {
          ...props,
          ...attrs,
          ...extraProps,
        },
        slots,
      );
    },
    DatePicker: (props, { attrs, slots }) => {
      const { name, id, type } = props;
      const extraProps: Recordable<any> = {};
      if (type && type.includes('range')) {
        if (name && !Array.isArray(name)) {
          extraProps.name = [name, `${name}_end`];
        }
        if (id && !Array.isArray(id)) {
          extraProps.id = [id, `${id}_end`];
        }
      }
      return h(
        withDefaultClearable(ElDatePicker, { type: 'daterange' }),
        {
          ...props,
          ...attrs,
          ...extraProps,
        },
        slots,
      );
    },
    RangeDatePicker,
    TreeSelect: withDefaultPlaceholder(
      withDefaultClearable(ElTreeSelect),
      'select',
    ),
    Upload: ElUpload,
  };

  // 将组件注册到全局共享状态中
  globalShareState.setComponents(components);

  // 定义全局共享状态中的消息提示
  globalShareState.defineMessage({
    // 复制成功消息提示
    copyPreferencesSuccess: (title, content) => {
      ElNotification({
        title,
        message: content,
        position: 'bottom-right',
        duration: 0,
        type: 'success',
      });
    },
  });
}
/**
 * 范围时间选择器配置项
 */
interface RangeDatePickerProps
  extends Omit<DatePickerProps, 'rangeSeparator' | 'type'> {
  /** 字段名前缀（自动生成 name/id） */
  fieldPrefix?: string;
  /** 是否强制使用 range 模式 */
  forceRange?: boolean;
  /** 自定义开始时间字段名 */
  startField?: string;
  /** 自定义结束时间字段名 */
  endField?: string;
  /** 开始时间占位符 */
  startPlaceholder?: string;
  /** 结束时间占位符 */
  endPlaceholder?: string;
  /** 范围分隔符 */
  rangeSeparator?: string;
  type: string;
}

/**
 * 智能范围时间选择器组件
 */
export const RangeDatePicker = (
  props: RangeDatePickerProps,
  { attrs, slots },
) => {
  const {
    type = 'daterange',
    fieldPrefix = 'date',
    forceRange = true,
    startField,
    endField,
    startPlaceholder = '开始日期',
    endPlaceholder = '结束日期',
    rangeSeparator = '-',
    ...restProps
  } = props;

  // 判断是否为范围选择模式
  const isRangeType = forceRange || (type && type.includes('range'));

  // 处理 range 模式的特殊逻辑
  // 新增一个允许 name/id 为数组的扩展类型
  type ExtendedDatePickerProps = DatePickerProps & {
    id?: string | string[];
    name?: string | string[];
  };
  const extraProps: Partial<ExtendedDatePickerProps> = {};

  if (isRangeType) {
    // 动态生成字段名
    const startName = startField || `${fieldPrefix}_start`;
    const endName = endField || `${fieldPrefix}_end`;

    // 处理 name 和 id 的数组化
    if (restProps.name && !Array.isArray(restProps.name)) {
      extraProps.name = [startName, endName];
    }
    if (restProps.id && !Array.isArray(restProps.id)) {
      extraProps.id = [startName, endName];
    }

    // 添加 range 专用属性
    Object.assign(extraProps, {
      'start-placeholder': attrs['start-placeholder'] || startPlaceholder,
      'end-placeholder': attrs['end-placeholder'] || endPlaceholder,
      'range-separator': attrs['range-separator'] || rangeSeparator,
    });
  }

  return h(
    ElDatePicker,
    {
      type: isRangeType ? type : undefined, // 非 range 模式不强制类型
      ...restProps,
      ...attrs,
      ...extraProps,
    },
    slots,
  );
};
const withDefaultPlaceholder = <T extends Component>(
  component: T,
  type: 'input' | 'select',
  componentProps: Recordable<any> = {},
) => {
  return defineComponent({
    inheritAttrs: false,
    name: component.name || 'WithDefaultPlaceholder',
    setup(props: any, { attrs, expose, slots }) {
      // Element Plus 的 placeholder 属性名就是 'placeholder'
      const placeholder =
        props?.placeholder ||
        attrs?.placeholder ||
        $t(`ui.placeholder.${type}`);

      // 处理组件引用和方法暴露
      const innerRef = ref();

      // 暴露组件方法
      expose({
        focus: () => innerRef.value?.focus?.(),
        blur: () => innerRef.value?.blur?.(),
        // 暴露内部组件的所有方法
        ...(innerRef.value ? { innerRef } : {}),
      });

      return () =>
        h(
          component,
          {
            ...componentProps,
            placeholder,
            ...attrs,
            ...props,
            ref: innerRef,
          },
          slots,
        );
    },
  });
};

// 添加 clearable 属性
const withDefaultClearable = <T extends Component>(
  component: T,
  componentProps: Recordable<any> = {},
) => {
  return defineComponent({
    inheritAttrs: false,
    name: component.name,
    setup(props: any, { attrs, expose, slots }) {
      // 添加 clearable 默认值
      const clearable = props.clearable ?? true;

      const innerRef = ref();

      // 使用Proxy动态转发方法调用到内部组件实例
      const publicApi = new Proxy({} as Record<string, any>, {
        get(target, prop: string) {
          return (...args: any[]) => {
            if (innerRef.value && typeof innerRef.value[prop] === 'function') {
              return innerRef.value[prop](...args);
            }
            // 可选：添加错误处理或警告
            console.warn(`Method ${prop} not found on inner component`);
          };
        },
      });

      expose(publicApi);

      return () =>
        h(
          component,
          {
            clearable,
            ...componentProps,
            ...props,
            ...attrs,
            ref: innerRef,
          },
          slots,
        );
    },
  });
};

// 添加组件处理自动完成的默认行为
const withDefaultAutocomplete = <T extends Component>(
  component: T,
  componentProps: Recordable<any> = {},
) => {
  return defineComponent({
    inheritAttrs: false,
    name: component.name,
    setup: (props: any, { attrs, expose, slots }) => {
      // 默认配置
      const defaults = {
        clearable: true,
        placeholder: $t('ui.placeholder.input'),
        highlightFirstItem: true,
        ...componentProps,
      };

      // 定义 timeout 变量，用于防抖
      let timeout: null | ReturnType<typeof setTimeout> = null;

      // 处理异步方法的防抖
      const debouncedFetch = (query: string, cb: (data: any[]) => void) => {
        if (props.fetchSuggestions) {
          const debounceTime = props.debounce ?? 300;

          // 清除之前的定时器
          if (timeout) {
            clearTimeout(timeout);
            timeout = null;
          }

          timeout = setTimeout(() => {
            props.fetchSuggestions(query, cb);
          }, debounceTime);
        }
      };

      // 暴露组件方法
      const innerRef = ref();
      const publicApi: Recordable<any> = {};
      expose(publicApi);
      const instance = getCurrentInstance();
      instance?.proxy?.$nextTick(() => {
        for (const key in innerRef.value) {
          if (typeof innerRef.value[key] === 'function') {
            publicApi[key] = innerRef.value[key];
          }
        }
      });

      return () =>
        h(
          component,
          {
            ...defaults,
            ...props,
            ...attrs,
            ref: innerRef,
            onFetchSuggestions: debouncedFetch,
          },
          slots,
        );
    },
  });
};

export { initComponentAdapter };
